package org.totoro.concurrent.sync.mark_word.state;

import lombok.SneakyThrows;
import org.totoro.concurrent.sync.mark_word.MarkWordStrategyAbs;

import java.math.BigInteger;
import java.util.List;

/**
 * Normal 策略 无锁
 * <p>
 * |------------------------------------------------------------------------------|--------------------|
 * |                                  Mark Word (64 bits)                         |       State        |
 * |------------------------------------------------------------------------------|--------------------|
 * | unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:1 | lock:2 |       Normal       | (01)无锁
 * |------------------------------------------------------------------------------|--------------------|
 * | thread:54 |       epoch:2        | unused:1 | age:4 | biased_lock:1 | lock:2 |       Biased       | (01)偏向锁
 * |------------------------------------------------------------------------------|--------------------|
 * |                       ptr_to_lock_record:62                         | lock:2 | Lightweight Locked | (00)轻量级锁
 * |------------------------------------------------------------------------------|--------------------|
 * |                     ptr_to_heavyweight_monitor:62                   | lock:2 | Heavyweight Locked | (10)重量级锁
 * |------------------------------------------------------------------------------|--------------------|
 * |                                                                     | lock:2 |    Marked for GC   | (11)GC标记
 * |------------------------------------------------------------------------------|--------------------|
 * <p>
 *
 * <p>
 * |-------------------------------------------------------|--------------------|
 * |                  Mark Word (32 bits)                  |       State        |
 * |-------------------------------------------------------|--------------------|
 * | identity_hashcode:25 | age:4 | biased_lock:1 | lock:2 |       Normal       |
 * |-------------------------------------------------------|--------------------|
 * |  thread:23 | epoch:2 | age:4 | biased_lock:1 | lock:2 |       Biased       |
 * |-------------------------------------------------------|--------------------|
 * |               ptr_to_lock_record:30          | lock:2 | Lightweight Locked |
 * |-------------------------------------------------------|--------------------|
 * |               ptr_to_heavyweight_monitor:30  | lock:2 | Heavyweight Locked |
 * |-------------------------------------------------------|--------------------|
 * |                                              | lock:2 |    Marked for GC   |
 * |-------------------------------------------------------|--------------------|
 *
 * @author daocr
 * @date 2020/3/15
 */
public class NormalStrategy extends MarkWordStrategyAbs {


    public NormalStrategy(Object instance) {
        super(instance);
    }


    public void printHashCode() {

        int code = instance.hashCode();
        System.out.println("\nhash code ：" + code + " hex ：" + Long.toHexString(code) + "\t\tBinary：" + binaryToDecimal(code, 31));

    }

    @SneakyThrows
    @Override
    public void print() {

        printHashCode();

        List<MarkWord> markWords = getMarkWords();

        super.printEasyRead(markWords);

        printType(markWords);

        super.printLayout();


    }

    @Override
    public void printType(List<MarkWord> markWords) {

        String easyRead = getEasyRead(markWords);

        BigInteger easyReadBigInteger = new BigInteger(easyRead.replace(" ", ""), 2);

        String lock_str = findOffsetCode(easyReadBigInteger, LOCK_OFFSET);
        String biased_lock_str = findOffsetCode(easyReadBigInteger, BIASED_LOCK_OFFSET);
        String age_offset_str = findOffsetCode(easyReadBigInteger, AGE_OFFSET);
        String hash_code_str = findOffsetCode(easyReadBigInteger, HASHCODE_OFFSET);

        System.out.println("lock :" + lock_str + "|\t是否启动偏向锁：" + biased_lock_str + "|\tage：" + age_offset_str + "|\thash code :" + hash_code_str);

    }


    public String reverse(String str) {
        return new StringBuilder(str).reverse().toString();
    }

}
